package com.excesys.util;

import com.fasterxml.jackson.core.JsonParser.Feature;
import com.fasterxml.jackson.core.json.JsonReadFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalTimeSerializer;
import lombok.extern.slf4j.Slf4j;

import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;

@Slf4j
public class JSONUtil {

    private static ObjectMapper mapper = new ObjectMapper();

    private static ObjectMapper mapperDate = new ObjectMapper();

    private static ObjectMapper mapperNotHtml = new ObjectMapper();

    private static String localDateTimeFormat = "yyyy-MM-dd HH:mm:ss";

    private static String localDateFormat = "yyyy-MM-dd";

    private static String localTimeFormat = "HH:mm:ss";

    static {
        // 设置 json 属性名称和字符串值可不使用双引号包住
        mapper.configure(Feature.ALLOW_UNQUOTED_FIELD_NAMES, true);
        // 设置 josn 是否允许单引号来包住属性名称和字符串值
        mapper.configure(Feature.ALLOW_SINGLE_QUOTES, true);
        // 允许出现特殊字符和转义符
        mapper.configure(JsonReadFeature.ALLOW_UNESCAPED_CONTROL_CHARS.mappedFeature(), true);
        JavaTimeModule javaTimeModule = new JavaTimeModule();
        // 序列化
        javaTimeModule.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(DateTimeFormatter.ofPattern(localDateTimeFormat)));
        javaTimeModule.addSerializer(LocalDate.class, new LocalDateSerializer(DateTimeFormatter.ofPattern(localDateFormat)));
        javaTimeModule.addSerializer(LocalTime.class, new LocalTimeSerializer(DateTimeFormatter.ofPattern(localTimeFormat)));
        // 反序列化
        javaTimeModule.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern(localDateTimeFormat)));
        javaTimeModule.addDeserializer(LocalDate.class, new LocalDateDeserializer(DateTimeFormatter.ofPattern(localDateFormat)));
        javaTimeModule.addDeserializer(LocalTime.class, new LocalTimeDeserializer(DateTimeFormatter.ofPattern(localTimeFormat)));
        mapper.registerModule(javaTimeModule);
        mapperDate.registerModule(javaTimeModule);
        mapperNotHtml.registerModule(javaTimeModule);
    }

    /**
     * json转对象
     *
     * @param json
     * @param valueType
     * @return
     */
    public static <T> T readValue(String json, Class<T> valueType) {
        try {
            return mapper.readValue(json, valueType);
        } catch (Exception e) {
            log.error("error", e);
        }
        return null;
    }

    /**
     * JSON格式化
     *
     * @param obj
     * @return
     */
    public static String toString(Object obj) {
        String json = null;
        try {
            json = mapper.writeValueAsString(obj);
        } catch (Exception e) {
            log.error("error", e);
        }
        return json;
    }

    /**
     * JSON格式化 是否转义html
     *
     * @param obj
     * @param isHtmlEscaping
     * @return
     */
    public static String toString(Object obj, boolean isHtmlEscaping) {
        mapperNotHtml.configure(JsonReadFeature.ALLOW_UNESCAPED_CONTROL_CHARS.mappedFeature(), !isHtmlEscaping);
        String json = null;
        try {
            json = mapperNotHtml.writeValueAsString(obj);
        } catch (Exception e) {
            log.error("error", e);
        }
        return json;
    }

    /**
     * JSON日期时间格式化
     *
     * @param obj 默认(yyyy-MM-dd HH:mm:ss)
     * @return
     */
    public static String toDateTime(Object obj) {
        return toFormatDateTime(obj, "yyyy-MM-dd HH:mm:ss");
    }

    /**
     * JSON日期格式化
     *
     * @param obj 默认(yyyy-MM-dd)
     * @return
     */
    public static String toDate(Object obj) {
        return toFormatDateTime(obj, "yyyy-MM-dd");
    }

    /**
     * JSON自定义日期时间格式化
     *
     * @param obj
     * @param dateFormat
     * @return
     */
    public static String toFormatDateTime(Object obj, String dateFormat) {
        SimpleDateFormat sdf = new SimpleDateFormat(dateFormat);
        mapperDate.setDateFormat(sdf);
        String json = null;
        try {
            json = mapperDate.writeValueAsString(obj);
        } catch (Exception e) {
            log.error("error", e);
        }
        return json;
    }

}
